home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 May / PCWorld_2003-05_cd.bin / Software / Vyzkuste / divfix / Perl version / DIVFIX < prev   
Text File  |  2002-05-05  |  8KB  |  305 lines

  1. #!/usr/bin/env perl
  2.  
  3. use Getopt::Std;
  4.  
  5. $KeyFrame = 16;
  6. $NormFrame = 0;
  7.  
  8. sub writeint {
  9.     my $fh = shift;
  10.     my $i = shift;
  11.  
  12.     print $fh pack "i",$i;
  13. }
  14.  
  15. sub readint {
  16.     my $fh = shift;
  17.     my $buf;
  18.  
  19.     read $fh,$buf,4;
  20.     return unpack "i",$buf;
  21. }
  22.  
  23. if (!getopts('vbd') || $#ARGV < 0)
  24. {
  25.     die <<"END";
  26. Usage: $0 [-v] [-b[d]] avifile ...
  27.          -v: verbose, progress meter
  28.          -b: keep backup
  29.          -d: discard bad parts (only valid with -b)
  30. END
  31. }
  32. $KeepBackup = $opt_b;
  33. $DiscardBadParts = $opt_d;
  34. $verbose = $opt_v;
  35.  
  36. foreach $filename (@ARGV) {
  37.     $InputSize = -s $filename;
  38.     $OutputName = $filename . ".tmp.idx";
  39.     $BackupName = $filename . ".DivFix";
  40.  
  41.     open Input,"+<$filename"  or  die "Cannot open $filename: $!\n";
  42.     open Output,"+>$OutputName"  or  die "Cannot open temporary file $OutputName: $!\n";
  43.     if ($KeepBackup) {
  44.           open Backup,">$BackupName"  or  do {
  45.             unlink $OutputName;
  46.             die "Cannot open $BackupName: $!\n";
  47.             }
  48.           }
  49.  
  50.     seek Input,8,0;
  51.     read Input,$ChunkName,8;
  52.     if ($ChunkName ne 'AVI LIST') { die "$filename: not an AVI file.\n"; }
  53.     if ($verbose) { print "Rebuilding index of $filename...\n"; }
  54.     $Position=16;
  55.     $Size=0;
  56.     do {
  57.       $Position += $Size;
  58.       seek Input,$Position,0;
  59.       $Size = readint(Input);
  60.       read Input,$ChunkName,4;
  61.       $Position += 8;
  62.     } until ($ChunkName eq 'movi');
  63.     $StreamStart=$Position-4;
  64.     $StreamSize=$Size;
  65.     $ChunkName='idx1';
  66.     print Output $ChunkName;
  67.     writeint(Output,$Size);
  68.     $Position=4;
  69.     $i=0;
  70.     $Frame=0;
  71.     $Difference=0;
  72.     $Interleaved=0;
  73.     seek Input,0,0;
  74.     if ($KeepBackup)
  75.     {
  76.       read Input,$Buffer,$StreamStart+4;
  77.       print Backup $Buffer;
  78.     }
  79.     do {
  80.       if ($verbose) {
  81.           printf "%2.1f%     \r", $Position * 100.0 / $InputSize;
  82.           }
  83.       seek Input,$StreamStart+$Position,0;
  84.       if (! eof Input) {
  85.         BStartRead:
  86.         read Input,$ChunkName,4;
  87.         if ($ChunkName eq 'LIST')
  88.         {
  89.           seek Input,8,1;
  90.           $Position += 12;
  91.           goto BStartRead;
  92.         }
  93.         if ($ChunkName eq 'JUNK')
  94.         {
  95.           $Size = readint(Input);
  96.           $Position += $Size+8;
  97.           seek Input,$StreamStart+$Position,0;
  98.           goto BStartRead;
  99.         }
  100.         if ((substr($ChunkName,0,2) eq 'ix') || (substr($ChunkName,2,2) eq 'ix'))
  101.         {
  102.           seek Input,12,1;
  103.           $Position += 16;
  104.           seek Input,$StreamStart+$Position,0;
  105.           $Interleaved=1;
  106.           goto BStartRead;
  107.         }
  108.         if (! eof Input)
  109.         {
  110.           # if ((($ChunkName[1] In Number) && ($ChunkName[2] In Number)) && ((Copy($ChunkName,3,2) eq 'dc') || (Copy($ChunkName,3,2) eq 'db') || (Copy($ChunkName,3,2) eq 'wb')))
  111.           if ($ChunkName =~ m/^\d\d(dc|db|wb)/o)
  112.           {
  113.             $Frame++;
  114.             if ($Interleaved)
  115.             {
  116.               seek Input,-16,1;
  117.               $Position -= 16;
  118.               $Interleaved=0;
  119.             }
  120.             $Temp = read Input,$TempBuf,4;
  121.             $Size = unpack "i",$TempBuf;
  122.             if (($Size<0) && ($Temp==4))
  123.             {
  124.               $Position += 4;
  125.               seek Input,$StreamStart+$Position,0;
  126.               read Input,$ChunkName,4;
  127.               if ($ChunkName eq 'LIST')
  128.               {
  129.                 seek Input,8,1;
  130.                 $Position += 12;
  131.                 goto BStartRead;
  132.               }
  133.               if ($ChunkName eq 'JUNK')
  134.               {
  135.                 $Size = readint(Input);
  136.                 $Position += $Size+8;
  137.                 seek Input,$StreamStart+$Position,0;
  138.                 goto BStartRead;
  139.               }
  140.               seek Input,$StreamStart+$Position,0;
  141.               goto BError;
  142.             }
  143.             if (! eof Input)
  144.             {
  145.               read Input,$FrameType,1;
  146.               $j=((($Position+$Size) >> 1)+(($Position+$Size) % 2))*2+8;
  147.                seek Input,$StreamStart+$j-1,0;
  148.                if (! eof Input) {
  149.                   if (length($ChunkName) != 4) {
  150.                     $ChunkName = substr($ChunkName . "    ",0,4);
  151.                     }
  152.                 print Output $ChunkName;
  153.                 # if (((Copy($ChunkName,3,2) eq 'dc') || (Copy($ChunkName,3,2) eq 'db') || (Copy($ChunkName,3,2) eq 'wb')) && (($ChunkName[1] In Number) && ($ChunkName[2] In Number)) && (($FrameType & 64)==0))
  154.                 if ($ChunkName =~ m/^\d\d(dc|db|wb)/o && (($FrameType & 64)==0)) {
  155.                       writeint(Output,$KeyFrame)
  156.                     }
  157.                 else {
  158.                       writeint(Output,$NormFrame);
  159.                     }
  160.                 if ($DiscardBadParts) {
  161.                   $j=$Position-$Difference;
  162.                   writeint(Output,$j)
  163.                 }
  164.                 else {
  165.                       writeint(Output,$Position);
  166.                   }
  167.                 writeint(Output,$Size);
  168.                 $j=$Position;
  169.                 $Position=((($Position+$Size) >> 1)+(($Position+$Size) % 2))*2+8;
  170.                 seek Input,$StreamStart+$j,0;
  171.                 if ($KeepBackup)
  172.                 {
  173.                   if ($Position-$j>32768)
  174.                   {
  175.                     for ($k=1;$k <= int (($Position-$j) / 32768);$k++)
  176.                     {
  177.                       read Input,$Buffer,32768;
  178.                       print Backup $Buffer;
  179.                     }
  180.                     read Input,$Buffer,(($Position-$j) % 32768);
  181.                     print Backup $Buffer;
  182.                   }
  183.                   else
  184.                   {
  185.                     read Input,$Buffer,$Position-$j;
  186.                     print Backup $Buffer;
  187.                   }
  188.                 }
  189.                 $i++;
  190.                }
  191.              }
  192.           }
  193.           else {
  194.             BError:
  195.             if ($ChunkName ne 'idx1')
  196.             {
  197.                 print "  Corrupted data detected at frame $$Frame\n";
  198.                 print "  Error offset: ",$StreamStart+$Position,"\n";
  199.                 # Shouldn't this > be a >= 
  200.               if (tell Output > 16) { seek Output,-16,1; }
  201.               $j=$Position;
  202.               do {
  203.                 seek Input,$StreamStart+$Position,0;
  204.                 if (! eof Input)
  205.                 {
  206.                   read Input,$Buffer,32768;
  207.                   $k=1;
  208.                   do {
  209.                     if (((substr($Buffer,$k-1,1) eq 'd') || (substr($Buffer,$k-1,1) eq 'w')) && (! eof Input))
  210.                     {
  211.                       if (((substr($Buffer,$k,1) eq 'c') || (substr($Buffer,$k,1) eq 'b')) && (! eof Input))
  212.                        {
  213.                         seek Input,$StreamStart+$Position+$k-3,0;
  214.                          if (! eof Input) {read Input,$ChunkName,4; }
  215.                        }
  216.                      }
  217.                     $k++;
  218.                   # right-brace until ((((Copy($ChunkName,3,2) eq 'dc') || (Copy($ChunkName,3,2) eq 'db') || (Copy($ChunkName,3,2) eq 'wb')) && (($ChunkName[1] In Number) && ($ChunkName[2] In Number))) || ($ChunkName eq 'idx1') || ($k>32768));
  219.                   } until (($ChunkName =~ m/^\d\d(dc|db|wb)/o) || ($ChunkName eq 'idx1') || ($k>32768));
  220.                 }
  221.                 $Position += $k-3;
  222.               # right-brace until ((((Copy($ChunkName,3,2) eq 'dc') || (Copy($ChunkName,3,2) eq 'db') || (Copy($ChunkName,3,2) eq 'wb')) && (($ChunkName[1] In Number) && ($ChunkName[2] In Number))) || ($ChunkName eq 'idx1') || eof Input);
  223.               } until (($ChunkName =~ m/^\d\d(dc|db|wb)/o) || ($ChunkName eq 'idx1') || eof Input);
  224.                if (! eof Input) { $Position--; }
  225.               if ($KeepBackup)
  226.               {
  227.                 if (!($DiscardBadParts))
  228.                 {
  229.                   seek Input,$StreamStart+$j,0;
  230.                   if ($Position-$j>32768)
  231.                   {
  232.                     for ($k=1; $k <= int (($Position-$j) / 32768);$k++)
  233.                      {
  234.                       read Input,$Buffer,32768;
  235.                       print Backup $Buffer;
  236.                      }
  237.                      read Input,$Buffer,(($Position-$j) % 32768);
  238.                       print Backup $Buffer;
  239.                   }
  240.                   else
  241.                   {
  242.                     read Input,$Buffer,$Position-$j;
  243.                     print Backup $Buffer;
  244.                   }
  245.                 }
  246.                 else { $Difference+=$Position-$j; }
  247.               }
  248.             }
  249.             else
  250.             {
  251.               seek Input,6,1;
  252.               read Input,$ChunkName,2;
  253.               seek Input,-8,1;
  254.               if (($ChunkName eq 'dc') || ($ChunkName eq 'wb') || ($ChunkName eq 'db'))
  255.               {
  256.                 $ChunkName='idx1';
  257.               }
  258.               else
  259.               {
  260.                 $ChunkName='0000';
  261.                 goto BError;
  262.               }
  263.             }
  264.           }
  265.         }
  266.       }
  267.     } until ((eof Input) || ($ChunkName eq 'idx1'));
  268.     $Size=$i*16;
  269.     seek Output,4,0;
  270.     writeint(Output,$Size);
  271.     if ($KeepBackup)
  272.     {
  273.       seek Backup,0,2;
  274.       $StreamSize=tell(Backup) - $StreamStart;
  275.       seek Backup,$StreamStart-4,0;
  276.       writeint(Backup,$StreamSize);
  277.       seek Backup,$StreamStart+$StreamSize,0;
  278.       seek Output,0,0;
  279.       do {
  280.          $Temp = read Output,$Buffer,32768;
  281.          print Backup $Buffer;
  282.       } until (!($Temp==32768));
  283.       truncate Backup, tell Backup;
  284.       close Backup;
  285.     }
  286.     else
  287.     {
  288.       seek Input,0,2;
  289.       $StreamSize=tell(Input) - $StreamStart;
  290.       seek Input,$StreamStart-4,0;
  291.       writeint(Input,$StreamSize);
  292.       seek Input,$StreamStart+$StreamSize,0;
  293.       seek Output,0,0;
  294.       do {
  295.          $Temp = read Output,$Buffer,32768;
  296.          print Input $Buffer;
  297.       } until (!($Temp==32768));
  298.       truncate Input, tell Input;
  299.     }
  300.     close Input;
  301.     close Output;
  302.     unlink $OutputName;
  303.     if ($verbose) { print "Done. \n"; }
  304. }
  305.